package com.foreverwin.jzymes.websocket;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.domain.TwoHourYield;
import com.foreverwin.jzymes.common.mapper.DashBoardAdviceMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.framework.annotation.WebSocketHandler;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.websocket.TextMessageWebSocketWraper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@WebSocketHandler(channel = "Z_DB_TWO_HOUR_YIELD")
public class TwoHourHandler extends TextMessageWebSocketWraper {

    @Autowired
    IProductionShiftService productionShiftService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    IActivityRuleAdviceService activityRuleAdviceService;
    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    WebSocketService webSocketService;
    @Autowired
    DashBoardAdviceMapper dashBoardAdviceMapper;

    private Map<String,String> activityRuleMap;


    public TwoHourHandler(){
        events = new ArrayList();
        events.add( "TWO_HOUR_CHECK_OUT" );
    }


    @Override
    public void doAfterOpen(Connection connection) {
        activityRuleMap = activityRuleAdviceService.findActivityRules( getChannel() );
    }

    @Override
    public void doAfterClose() {

    }

    @Override
    public JSONObject doReceiveAndReply(String messageType, JSONObject requestParams) {
        if( "WS_INIT_DATA".equals( messageType ) ){
            buildTwoHourData();
        }
        return null;
    }

    @Override
    public void onAppEvent(AppEvent<?> appEvent) {
        String event = appEvent.getName();
        if( "TWO_HOUR_CHECK_OUT".equals( event ) ){
            buildTwoHourData();
        }
    }

    public void buildTwoHourData(  ){
        String site = activityRuleMap.get( "SITE" );
        String aShift = activityRuleMap.get( "DAY_SHIFT" );
        String inspect = activityRuleMap.get( "INSPECT" );

        JSONObject response = new JSONObject();
        JSONArray yieldArray = new JSONArray();

        JSONObject allTotal = new JSONObject();
        allTotal.put( "id", "allTotal" );
        allTotal.put( "plan", 0L );
        allTotal.put( "diff", 0L );
        yieldArray.add( allTotal );

        JSONObject dayTotal = new JSONObject();
        dayTotal.put( "id", "dayTotal" );
        dayTotal.put( "plan", 0L );
        dayTotal.put( "diff", 0L );
        yieldArray.add( dayTotal );

        JSONObject nightTotal = new JSONObject();
        nightTotal.put( "id", "nightTotal" );
        nightTotal.put( "plan", 0L );
        nightTotal.put( "diff", 0L );
        yieldArray.add( nightTotal );

        Map<String,JSONObject> tempMap = new HashMap<>();

        Date[] dateRange = productionShiftService.findShiftRange( site, aShift );
        Date[] dayRange = productionShiftService.findProductionDayRange( site );
        Long planQty = getPlanQty( site, dayRange );

        List<TwoHourYield> aYieldList = dashBoardAdviceMapper.findTwoHourYieldByDateRange( site, dayRange[0], dayRange[1] );
        for( TwoHourYield aYield : aYieldList ){
            JSONObject timeYield = null;
            String timeRange = aYield.getTimeRange();
            String operation = aYield.getOperation();
            String itemBo = aYield.getItemBo();
            Date startDateTime = aYield.getStartDateTime();

            if( itemBo != null ){
                String itemLabel = customFieldsAdviceService.findCustomValue( itemBo, Constants.ITEM_CUSTOM_FIELD_ITEM_LABEL );
                operation = operation + "-" + itemLabel;
            }
            //operation = activityRuleMap.get( operation );

            if( tempMap.containsKey( timeRange ) ){
                timeYield = tempMap.get( timeRange );
            }else{
                timeYield = new JSONObject();
                timeYield.put( "id", timeRange );
                timeYield.put( "plan", planQty );
                tempMap.put( timeRange, timeYield );
                yieldArray.add( timeYield );
                if( startDateTime.before( dateRange[1] ) ){
                    dayTotal.put( "plan", dayTotal.getLong( "plan" ) + planQty  );
                }else{
                    nightTotal.put( "plan", nightTotal.getLong( "plan" ) + planQty  );
                }
                allTotal.put( "plan", allTotal.getLong( "plan" ) + planQty  );
            }
            timeYield.put( operation, aYield.getQty());

            if( startDateTime.before( dateRange[1] ) ){
                if( dayTotal.containsKey( operation ) ){
                    dayTotal.put( operation, dayTotal.getLong( operation ) + aYield.getQty()  );
                }else{
                    dayTotal.put( operation, aYield.getQty() );
                }
                if( operation.equals( inspect ) ){
                    dayTotal.put( "diff", dayTotal.getLong(  operation ) - dayTotal.getLong( "plan" )  );
                }
            }else{
                if( nightTotal.containsKey( operation ) ){
                    nightTotal.put( operation, nightTotal.getLong( operation ) + aYield.getQty() );
                }else{
                    nightTotal.put( operation, aYield.getQty() );
                }
                if( operation.equals( inspect ) ){
                    nightTotal.put( "diff", nightTotal.getLong(  operation ) - nightTotal.getLong( "plan" ) );
                }
            }

            if( allTotal.containsKey( operation ) ){
                allTotal.put( operation, allTotal.getLong( operation ) + aYield.getQty() );
            }else{
                allTotal.put( operation, aYield.getQty() );
            }

            if( operation.equals( inspect ) ){
                timeYield.put( "diff",  timeYield.getLong( operation ) - planQty );
                allTotal.put( "diff", allTotal.getLong(  operation ) - allTotal.getLong( "plan" ) );
            }
        }

        response.put( "data", yieldArray );
        sendMessage( response );
    }

    public Long getPlanQty( String site, Date[] dayRange ){

        int hourInterval = Integer.valueOf( systemRuleAdviceService.findSystemRule( site, Constants.SYSTEM_RULE_TWO_HOUR, "2" ) );
        Long times = ( dayRange[1].getTime() - dayRange[0].getTime() ) / ( hourInterval * 60 * 60 * 1000 );
        String itemGroup = itemGroupAdviceService.findItemGroupBySite( site );
        List<Map<String,Object>> itemMemberList = itemGroupAdviceService.findItemGroupMember( site, itemGroup );
        if( itemMemberList.size() > 0 ){
            String customValue = customFieldsAdviceService.findCustomValue( (String) itemMemberList.get( 0 ).get( "ITEM_BO" ), Constants.ITEM_CUSTOM_FIELD_PLAN_QTY );
            if( StringUtils.isNotBlank( customValue ) ){
                Long plantQty = Long.valueOf( customValue );
                return plantQty / times;
            }
        }
        return 0L;
    }
}
